package org.example.day03;

/**
 * @author zlxad
 * @version 1.0
 * @description: TODO
 * <p>  <br> </p> <p>  请设计一个文件缓存系统，该文件缓存系统可以指定缓存的最大值（单位为字节）。<span></span>  </p> <p>  文件缓存系统有两种操作：存储文件<span>(put)</span>和读取文件<span>(get)</span>  </p> <p>  操作命令为<span>put fileName fileSize</span>或者<span>get fileName</span>  </p> <p>  存储文件是把文件放入文件缓存系统中；读取文件是从文件缓存系统中访问已存在的文件，如果文件不存在，则不作任何操作。<span></span>  </p> <p>  当缓存空间不足以存放新的文件时，根据规则删除文件，直到剩余空间满足新的文件大小为止，再存放新文件。<span><br> </span>具体的删除规则为：<span><br> </span>文件访问过后，会更新文件的最近访问时间和总的访问次数，当缓存不够时，按照第一优先顺序为访问次数从少到多，第二顺序为时间从老到新的方式来删除文件。 </p>
 *
 * 请设计一个文件缓存系统，该文件缓存系统可以指定缓存的最大值（单位为字节）。
 * 文件缓存系统有两种操作：存储文件(put)和读取文件(get)
 * 操作命令为put fileName fileSize或者get fileName
 * 存储文件是把文件放入文件缓存系统中；读取文件是从文件缓存系统中访问已存在的文件，如果文件不存在，则不作任何操作。
 * 当缓存空间不足以存放新的文件时，根据规则删除文件，直到剩余空间满足新的文件大小为止，再存放新文件。 具体的删除规则为：
 * 文件访问过后，会更新文件的最近访问时间和总的访问次数，当缓存不够时，按照第一优先顺序为访问次数从少到多，第二顺序为时间从老到新的方式来删除文件。
 * @date 2024/3/11 15:22
 */
import java.util.LinkedHashMap;
import java.util.Map;

class FileEntry {
    String fileName;
    long fileSize;
    long lastAccessTime;
    int accessCount;

    public FileEntry(String fileName, long fileSize) {
        this.fileName = fileName;
        this.fileSize = fileSize;
        this.lastAccessTime = System.currentTimeMillis();
        this.accessCount = 1;
    }

    // 更新文件的最后访问时间和访问次数
    public void updateAccess() {
        this.lastAccessTime = System.currentTimeMillis();
        this.accessCount++;
    }

    public long fileSize() {
        return fileSize;
    }
}
public class test060 {
    private final long maxCacheSize;
    private final LinkedHashMap<String, FileEntry> cache;

    public test060(long maxCacheSize) {
        this.maxCacheSize = maxCacheSize;
        // 设置LinkedHashMap的移除策略为访问顺序+访问次数
        this.cache = new LinkedHashMap<>(16, 0.75f, true) {
            @Override
            protected boolean removeEldestEntry(Map.Entry<String, FileEntry> eldest) {
                // 当缓存的总大小超过最大值时，移除最老的元素
                return size() > 0 && getTotalSize() > maxCacheSize;
            }
        };
    }

    public test060(long maxCacheSize, LinkedHashMap<String, FileEntry> cache) {
        this.maxCacheSize = maxCacheSize;
        this.cache = cache;
    }

    // 获取缓存中所有文件的大小总和
    private long getTotalSize() {
        return cache.values().stream().mapToLong(FileEntry::fileSize).sum();
    }

    // 存储文件
    public void put(String fileName, long fileSize) {
        if (fileSize <= 0) {
            throw new IllegalArgumentException("File size must be positive");
        }

        // 如果文件已存在，则更新其信息
        if (cache.containsKey(fileName)) {
            FileEntry existingEntry = cache.get(fileName);
            existingEntry.updateAccess();
            return;
        }

        // 尝试添加新文件到缓存
        FileEntry newEntry = new FileEntry(fileName, fileSize);
        cache.put(fileName, newEntry);
    }

    // 读取文件
    public void get(String fileName) {
        if (cache.containsKey(fileName)) {
            FileEntry entry = cache.get(fileName);
            entry.updateAccess();
        }
    }

    // 测试代码
    public static void main(String[] args) {
        test060 cacheSystem = new test060(1000); // 假设最大缓存为1000字节

        cacheSystem.put("file1", 500);
        cacheSystem.put("file2", 300);
        cacheSystem.get("file1");
        cacheSystem.put("file3", 700); // 这里会触发移除"file2"因为空间不足

        // 输出缓存中的文件信息
        for (Map.Entry<String, FileEntry> entry : cacheSystem.cache.entrySet()) {
            System.out.println("File: " + entry.getKey() +
                    ", Size: " + entry.getValue().fileSize +
                    ", Last Access: " + entry.getValue().lastAccessTime +
                    ", Access Count: " + entry.getValue().accessCount);
        }
    }
}